import {
  Injectable,
  NotFoundException,
  BadRequestException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, Between, In, MoreThanOrEqual } from 'typeorm';
import { Novel, NovelStatus } from './entities/novel.entity';
import { MasterCategory } from './entities/master-category.entity';
import { UserFavorite } from './entities/user-favorite.entity';
import { CategoryMappingService } from './services/category-mapping.service';
import {
  CreateNovelDto,
  UpdateNovelDto,
  NovelQueryDto,
} from './dto/create-novel.dto';
import {
  PaginationUtil,
  PaginationOptions,
} from '../../common/utils/pagination.util';

@Injectable()
export class NovelService {
  constructor(
    @InjectRepository(Novel)
    private novelRepository: Repository<Novel>,
    @InjectRepository(MasterCategory)
    private masterCategoryRepository: Repository<MasterCategory>,
    @InjectRepository(UserFavorite)
    private userFavoriteRepository: Repository<UserFavorite>,
    private categoryMappingService: CategoryMappingService,
  ) {}

  /**
   * 创建小说
   */
  async create(createNovelDto: CreateNovelDto): Promise<Novel> {
    const { masterCategoryId, ...novelData } = createNovelDto;

    // 验证母分类是否存在
    if (masterCategoryId) {
      const masterCategory = await this.masterCategoryRepository.findOne({
        where: { id: masterCategoryId },
      });
      if (!masterCategory) {
        throw new BadRequestException('母分类不存在');
      }
    }

    const novel = new Novel();
    Object.assign(novel, novelData);
    novel.masterCategoryId = masterCategoryId || null;
    novel.status = novelData.status || NovelStatus.SERIAL;
    novel.wordCount = novelData.wordCount || 0;
    novel.readCount = 0;
    novel.favoriteCount = 0;
    novel.ratingScore = novelData.ratingScore || 0;
    novel.ratingCount = 0;

    return this.novelRepository.save(novel);
  }

  /**
   * 分页查询小说
   */
  async findAll(query: NovelQueryDto = {}) {
    const {
      page = 1,
      limit = 10,
      masterCategoryId,
      keyword,
      sort = 'latest',
      status,
    } = query;
    const { limit: parsedLimit, offset } = PaginationUtil.parse({
      page,
      limit,
    });

    const whereCondition: any = {};

    // 分类过滤
    if (masterCategoryId) {
      whereCondition.masterCategoryId = masterCategoryId;
    }

    // 状态过滤
    if (status !== undefined) {
      whereCondition.status = status;
    } else {
      whereCondition.status = In([NovelStatus.SERIAL, NovelStatus.COMPLETED]);
    }

    // 关键词搜索
    if (keyword) {
      whereCondition.title = Like(`%${keyword}%`);
    }

    // 排序配置
    let order: any = {};
    switch (sort) {
      case 'latest':
        order = { updatedAt: 'DESC' };
        break;
      case 'popular':
        order = { readCount: 'DESC' };
        break;
      case 'rating':
        order = { ratingScore: 'DESC', ratingCount: 'DESC' };
        break;
      case 'favorite':
        order = { favoriteCount: 'DESC' };
        break;
      default:
        order = { updatedAt: 'DESC' };
    }

    const [novels, total] = await this.novelRepository.findAndCount({
      where: whereCondition,
      relations: ['masterCategory'],
      order,
      take: parsedLimit,
      skip: offset,
    });

    return PaginationUtil.createResponse(novels, total, { page, limit });
  }

  /**
   * 获取单个小说
   */
  async findOne(id: number, userId?: number): Promise<Novel & { isFavorited?: boolean; favoriteBookshelfId?: number | null }> {
    const novel = await this.novelRepository.findOne({
      where: { id },
      relations: ['masterCategory'],
    });

    if (!novel) {
      throw new NotFoundException('小说不存在');
    }

    // 如果提供了用户ID，查询用户是否已收藏该小说
    if (userId) {
      const favorite = await this.userFavoriteRepository.findOne({
        where: {
          userId,
          novelId: id,
        },
      });

      // 为小说对象添加收藏状态
      return {
        ...novel,
        isFavorited: !!favorite,
        favoriteBookshelfId: favorite?.bookshelfId || null,
      };
    }

    return novel;
  }

  /**
   * 更新小说
   */
  async update(id: number, updateNovelDto: UpdateNovelDto): Promise<Novel> {
    const novel = await this.findOne(id);
    const { masterCategoryId, ...updateData } = updateNovelDto;

    // 验证母分类是否存在
    if (masterCategoryId !== undefined && masterCategoryId !== null) {
      const masterCategory = await this.masterCategoryRepository.findOne({
        where: { id: masterCategoryId },
      });
      if (!masterCategory) {
        throw new BadRequestException('母分类不存在');
      }
      novel.masterCategoryId = masterCategoryId;
    }

    Object.assign(novel, updateData);
    return this.novelRepository.save(novel);
  }

  /**
   * 删除小说（软删除）
   */
  async remove(id: number): Promise<void> {
    const novel = await this.findOne(id);
    novel.status = NovelStatus.OFFLINE;
    await this.novelRepository.save(novel);
  }

  /**
   * 获取热门小说（基于热度算法）
   */
  async findPopularNovels(
    limit: number = 10,
    masterCategoryId?: number,
  ): Promise<Novel[]> {
    const whereCondition: any = {
      status: In([NovelStatus.SERIAL, NovelStatus.COMPLETED]),
    };

    if (masterCategoryId) {
      whereCondition.masterCategoryId = masterCategoryId;
    }

    // 获取所有符合条件的小说
    const novels = await this.novelRepository.find({
      where: whereCondition,
      relations: ['masterCategory'],
    });

    // 计算热度值并排序
    const sevenDaysAgo = new Date();
    sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);

    // 获取最大值用于标准化
    const maxRead = Math.max(...novels.map(n => n.readCount), 1);
    const maxFavorite = Math.max(...novels.map(n => n.favoriteCount), 1);

    const novelsWithHotScore = novels.map(novel => {
      // 模拟热度算法：阅读量 * 0.6 + 收藏增长率 * 0.4
      // 由于缺乏历史数据，使用总收藏量作为热度的代理指标
      const readScore = (novel.readCount / maxRead) * 10;
      const favoriteScore = (novel.favoriteCount / maxFavorite) * 10;

      // 计算收藏增长率（用评分人数作为活跃度指标）
      const activityScore = Math.log(Math.max(novel.ratingCount, 1)) / Math.log(10) * 2;

      let hotScore = readScore * 0.6 + favoriteScore * 0.4 + activityScore * 0.2;

      // 时间衰减因子：最近更新的小说权重更高
      const daysSinceUpdate = (Date.now() - novel.updatedAt.getTime()) / (1000 * 60 * 60 * 24);
      const timeDecay = Math.exp(-daysSinceUpdate / 30); // 30天衰减周期
      hotScore *= timeDecay;

      return {
        ...novel,
        hotScore
      };
    });

    // 按热度值排序并返回前N个，同时考虑分类平衡
    const sortedNovels = novelsWithHotScore
      .sort((a, b) => b.hotScore - a.hotScore);

    // 如果没有指定分类，进行分类平衡
    if (!masterCategoryId && sortedNovels.length > 5) {
      return this.balanceCategories(sortedNovels, limit);
    }

    return sortedNovels.slice(0, limit);
  }

  /**
   * 分类平衡算法，确保推荐结果包含多个分类
   */
  private balanceCategories(novels: any[], limit: number): any[] {
    const result: any[] = [];
    const categoryCount: { [key: number]: number } = {};
    const maxPerCategory = Math.ceil(limit / 2); // 每个分类最多占1/2，增加灵活性

    for (const novel of novels) {
      const categoryId = novel.masterCategoryId || 0;

      // 如果该分类书籍未达到上限，则添加
      if (!categoryCount[categoryId] || categoryCount[categoryId] < maxPerCategory) {
        result.push(novel);
        categoryCount[categoryId] = (categoryCount[categoryId] || 0) + 1;

        if (result.length >= limit) {
          break;
        }
      }
    }

    // 如果结果还不够，从剩余小说中补充（不考虑分类限制）
    if (result.length < limit) {
      const usedIds = new Set(result.map(n => n.id));
      const remainingNovels = novels.filter(n => !usedIds.has(n.id));

      const needed = limit - result.length;
      result.push(...remainingNovels.slice(0, needed));
    }

    return result.slice(0, limit);
  }

  /**
   * 获取最新小说
   */
  async findLatestNovels(
    limit: number = 10,
    masterCategoryId?: number,
  ): Promise<Novel[]> {
    const whereCondition: any = {
      status: In([NovelStatus.SERIAL, NovelStatus.COMPLETED]),
    };

    if (masterCategoryId) {
      whereCondition.masterCategoryId = masterCategoryId;
    }

    return this.novelRepository.find({
      where: whereCondition,
      relations: ['masterCategory'],
      order: { updatedAt: 'DESC' },
      take: limit,
    });
  }

  /**
   * 获取推荐小说（基于综合评分算法）
   */
  async findRecommendedNovels(
    limit: number = 10,
    masterCategoryId?: number,
  ): Promise<Novel[]> {
    const whereCondition: any = {
      status: In([NovelStatus.SERIAL, NovelStatus.COMPLETED]),
      ratingCount: MoreThanOrEqual(10), // 至少有10个评分
    };

    if (masterCategoryId) {
      whereCondition.masterCategoryId = masterCategoryId;
    }

    // 获取所有符合条件的小说
    const novels = await this.novelRepository.find({
      where: whereCondition,
      relations: ['masterCategory'],
    });

    // 计算综合评分并排序
    const threeMonthsAgo = new Date();
    threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);

    // 获取最大值用于标准化
    const maxFavorite = Math.max(...novels.map(n => n.favoriteCount), 1);
    const maxRead = Math.max(...novels.map(n => n.readCount), 1);

    const novelsWithScore = novels.map(novel => {
      // 综合评分算法：评分 * 0.4 + 收藏量标准化 * 0.3 + 阅读量标准化 * 0.3
      const favoriteScore = (novel.favoriteCount / maxFavorite) * 10;
      const readScore = (novel.readCount / maxRead) * 10;
      let comprehensiveScore = novel.ratingScore * 0.4 + favoriteScore * 0.3 + readScore * 0.3;

      // 新书加权：发布时间3个月内的书籍权重+20%
      if (novel.createdAt > threeMonthsAgo) {
        comprehensiveScore *= 1.2;
      }

      return {
        ...novel,
        comprehensiveScore
      };
    });

    // 按综合评分排序并返回前N个
    return novelsWithScore
      .sort((a, b) => b.comprehensiveScore - a.comprehensiveScore)
      .slice(0, limit);
  }

  /**
   * 增加阅读量
   */
  async incrementReadCount(id: number): Promise<void> {
    await this.novelRepository.increment({ id }, 'readCount', 1);
  }

  /**
   * 更新小说统计信息
   */
  async updateStats(
    id: number,
    stats: { wordCount?: number; ratingScore?: number; ratingCount?: number },
  ): Promise<void> {
    const novel = await this.findOne(id);

    if (stats.wordCount !== undefined) {
      novel.wordCount = stats.wordCount;
    }
    if (stats.ratingScore !== undefined) {
      novel.ratingScore = stats.ratingScore;
    }
    if (stats.ratingCount !== undefined) {
      novel.ratingCount = stats.ratingCount;
    }

    await this.novelRepository.save(novel);
  }

  /**
   * 搜索小说
   */
  async search(keyword: string, options: PaginationOptions = {}) {
    if (!keyword || keyword.trim().length === 0) {
      throw new BadRequestException('搜索关键词不能为空');
    }

    const { limit, offset } = PaginationUtil.parse(options);

    const [novels, total] = await this.novelRepository.findAndCount({
      where: [
        {
          title: Like(`%${keyword}%`),
          status: In([NovelStatus.SERIAL, NovelStatus.COMPLETED]),
        },
        {
          author: Like(`%${keyword}%`),
          status: In([NovelStatus.SERIAL, NovelStatus.COMPLETED]),
        },
      ],
      relations: ['masterCategory'],
      order: { readCount: 'DESC' },
      take: limit,
      skip: offset,
    });

    return PaginationUtil.createResponse(novels, total, options);
  }
}
